/***************************************************
> Copyright (C) 2025 ==ASD== All rights reserved.
> File Name: hw6.c
> Author: asd
> Mail:3319941451@qq.com 
> Created Time: 2025年01月03日 星期五 20时51分16秒
***************************************************/
//服务器端数据分发模块
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/epoll.h>
#include <signal.h>
#include <pthread.h>
#include <sys/mman.h>
#include <sys/ipc.h>
#include <sys/shm.h>

// 定义结构体存储客户端信息
typedef struct ClientInfo {
    int client_socket;
    struct sockaddr_in client_addr;
} ClientInfo;

// 全局变量，用于存储客户端信息数组
ClientInfo clients[100];
int client_count = 0;

// 共享内存相关变量
void *shared_memory;
int shared_memory_fd;

// 函数声明
void distribute_data(const char *data);
void *distribution_thread(void *arg);

int main() {
    // 创建UDP套接字用于数据分发
    int server_socket = socket(AF_INET, SOCK_DGRAM, 0);
    if (server_socket == -1) {
        perror("Socket creation failed");
        return 1;
    }

    // 设置服务器地址结构体
    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(6868);
    server_addr.sin_addr.s_addr = INADDR_ANY;

    // 绑定套接字到地址和端口
	int ret = 0;
	ret = bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr));
    if (ret == -1) 
	{
        perror("bind");
        exit(-1);
    }

    // 创建epoll实例
    int epoll_fd = epoll_create1(0);
    if (epoll_fd == -1) 
	{
        perror("Epoll create failed");
        exit(-1);
    }

    // 将服务器套接字添加到epoll监听事件中
    struct epoll_event event;
    event.events = EPOLLIN;
    event.data.fd = server_socket;
    if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_socket, &event) == -1) 
	{
        perror("Epoll ctl add server socket failed");
        return 1;
    }

    // 创建共享内存用于与其他模块共享数据
    shared_memory_fd = shmget(IPC_PRIVATE, sizeof(char) * 1024, IPC_CREAT | 0666);
    if (shared_memory_fd == -1) 
	{
        perror("shmget failed");
        return 1;
    }

    shared_memory = mmap(NULL, sizeof(char) * 1024, PROT_READ | PROT_WRITE, MAP_SHARED, shared_memory_fd, 0);
    if (shared_memory == MAP_FAILED) 
	{
        perror("mmap failed");
        return 1;
    }


    // 主循环，等待事件发生
    struct epoll_event events[10];
    while (1) {
        int num_events = epoll_wait(epoll_fd, events, 10, -1);
        if (num_events == -1) {
            perror("Epoll wait failed");
            break;
        }

        for (int i = 0; i < num_events; i++) {
            if (events[i].data.fd == server_socket) 
			{
                // 接受客户端连接（这里可以根据实际需求调整为仅接收客户端注册信息等）
                struct sockaddr_in client_addr;
                socklen_t client_addr_len = sizeof(client_addr);
                int client_socket = accept(server_socket, (struct sockaddr *)&client_addr, &client_addr_len);
                if (client_socket == -1) 
				{
                    perror("Accept failed");
                } else 
				{
                    // 将客户端信息存储到数组中
                    clients[client_count].client_socket = client_socket;
                    clients[client_count].client_addr = client_addr;
                    client_count++;

                    // 为每个客户端创建一个线程来分发数据
                    pthread_t thread_id;
                    pthread_create(&thread_id, NULL, distribution_thread, (void *)&client_socket);
                }
            }
        }
    }

    // 释放共享内存
    if (munmap(shared_memory, sizeof(char) * 1024) == -1) {
		
        perror("munmap failed");
    }
    if (shmctl(shared_memory_fd, IPC_RMID, NULL) == -1) 
	{
        perror("shmctl failed");
    }

    // 关闭服务器套接字
    close(server_socket);

    return 0;
}

void distribute_data(const char *data) 
{
    // 将数据通过UDP发送给所有客户端
	int ret = 0;
    for (int i = 0; i < client_count; i++) 
	{
		ret = sendto(clients[i].client_socket, data, strlen(data), 0,(struct sockaddr *)&clients[i].client_addr, sizeof(clients[i].client_addr));
        if (ret == -1) 
		{
            perror("Sendto failed");
        }
    }
}

void *distribution_thread(void *arg) {
    int client_socket = *(int *)arg;
    // 从共享内存中获取数据并发送给客户端
   void *data = (void *)shared_memory;
	
    distribute_data(data);
    pthread_exit(NULL);
}
